home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Audio / LPCView / Source / LPCPlot.m < prev    next >
Encoding:
Text File  |  1992-03-07  |  17.2 KB  |  832 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "LPCPlot.h"
  5. #import "LPCView.h"
  6. #import "Dispatcher.h"
  7. #import <appkit/Application.h>
  8. #import <appkit/Window.h>
  9. #import <appkit/ScrollView.h>
  10. #import <appkit/Panel.h>
  11. #import <appkit/Cell.h>
  12. #import <appkit/SavePanel.h>
  13. #import <strings.h>
  14. #import <sys/types.h>
  15. #import <sys/stat.h>
  16. #import <sys/file.h>
  17. #import <libc.h>
  18. #import <dpsclient/dpsclient.h>
  19. #import <math.h>
  20. #import <dpsclient/wraps.h>
  21. #import "PWfft.h"
  22.  
  23. /*
  24.  *  Frame information
  25.  */
  26. #define RESIDAMP    0
  27. #define AMP    1
  28. #define THRESH    2
  29. #define PITCH    3
  30.  
  31. #define MAXZOOM    4
  32. #define MINZOOM    -3
  33.  
  34. @implementation LPCPlot
  35.  
  36. extern int errno;
  37.  
  38. /*
  39.  *  Create a new document to display a LPC plot
  40.  */
  41. + new:(const char *)title
  42. {
  43.     NXRect aRect;
  44.     
  45.     self = [super new];
  46.     // Set up memory
  47.     PSops = NULL;
  48.     PSAdata = NULL;
  49.     PSPdata = NULL;
  50.     undoData = NULL;
  51.     undoSize = 0;
  52.     [NXApp loadNibSection:"lpcplot.nib" owner:self];
  53.     [myView setDelegate:self];
  54.     [myView setParent:self];
  55.     [myPlot setDelegate:self];
  56.     numBytes = 0;    
  57.     zoomfactor = 1;
  58.     curzoom = 0;
  59.     threshold = 1.0;
  60.     PWinit();
  61.     [self setDirty:NO];
  62.     
  63.     // Set up view dependencies
  64.     
  65.     [myScroll getDocVisibleRect:&aRect];
  66.     [myView setFrame:&aRect];
  67.     [myScroll setDocView:myView];
  68.     [myScroll setHorizScrollerRequired:YES];
  69.     [myScroll setVertScrollerRequired:NO];
  70.     
  71.     // Set the number of poles for the LPC file - get default from NXApp
  72.     [self setPoles:[NXApp poles]];        
  73.     [numPoles setIntValue:poles];
  74.     
  75.     // Set the title of the window - filename or Untitled 
  76.     strcpy(filename, title);
  77.     if (!strcmp(filename, "Untitled")) {
  78.         hasData = NO;
  79.         [myPlot setTitleAsFilename:"Untitled"];
  80.         [self show:self];
  81.         return self;
  82.     }
  83.     else {
  84.         [myPlot setTitleAsFilename:filename];
  85.         if ([self setLPCfile:filename] < 0) {
  86.             hasData = NO;
  87.             [myPlot setTitleAsFilename:"Untitled"];
  88.             [self show:self];
  89.             return self;
  90.         }
  91.         hasData = YES;
  92.     }
  93.     [self show:self];
  94.     return self;
  95. }
  96.  
  97. - (int) setLPCfile:(const char *)file
  98. {
  99.     struct stat st;
  100.     
  101.     openfd = open(file, O_RDWR, 0);
  102.     if (openfd < 0) {
  103.         [self error:"Could not open input file : ":errno];
  104.         return -1;
  105.     }
  106.     fstat(openfd, &st);
  107.     frames = (st.st_size/(([self getPoles] + 4)*4))-1;
  108.     numBytes = st.st_size;
  109.     [numFrames setIntValue:frames];
  110.     lpcData = (float *)malloc(st.st_size);
  111.     if (read(openfd, lpcData, st.st_size) < 0) {
  112.         [self error:"Error reading input file : ":errno];
  113.         return -1;
  114.     }
  115.     return 0;    
  116. }
  117.  
  118. - drawData
  119. {
  120.     int     i, winwidth, abovethresh, belowthresh;
  121.     float     yscalea, yscalep, half, zoomsize;
  122.     NXRect     viewBounds, scrollBounds, visBounds;
  123.     float    amax, amin;    // amplitude boundaries
  124.     float    ptchmax, ptchmin;    // pitch boundaries 
  125.     // DPSUserPath stuff
  126.     float    bbox[4];    
  127.     float    *t, *a, *ptch;    // temporary variables
  128.     float    *pitchT, *ampT;
  129.     char    *o;
  130.     
  131.     //  Only draw plot if such information exists
  132.     if (!hasData) 
  133.         return self;
  134.         
  135.     framesize = ([self getPoles] + 4);
  136.     amax = MINFLOAT;  ptchmax = MINFLOAT;
  137.     amin = MAXFLOAT;  ptchmin = MAXFLOAT;
  138.     
  139.     t = lpcData;
  140.     for (i = 0; i < frames; i++) {
  141.         if (t[AMP] > amax) 
  142.             amax = t[AMP];
  143.         if (t[AMP] < amin)
  144.             amin = t[AMP];
  145.         if (t[PITCH] > ptchmax)
  146.             ptchmax = t[PITCH];
  147.         if (t[PITCH] < ptchmin)
  148.             ptchmin = t[PITCH];
  149.         t += framesize;
  150.     }
  151.     if (amax == amin) {
  152.         if (amax > 0)
  153.             amin = 0;
  154.         else if (amax == 0)
  155.             amin = -1;
  156.         else 
  157.             amin = 2*amax;
  158.     }
  159.     if (ptchmax == ptchmin) {
  160.         if (ptchmax > 0)
  161.             ptchmin = 0;
  162.         else if (ptchmax == 0)
  163.             ptchmin = -1;
  164.         else
  165.             ptchmin = 2*ptchmax;
  166.     }
  167.     [myScroll getDocVisibleRect:&scrollBounds];
  168.     [myView getVisibleRect:&visBounds];
  169.     scrollBounds.size.width *= zoomfactor;
  170.     printf("width = %f\n", scrollBounds.size.width);
  171.     /* Bug in DSPUserpath makes drawing at > 4096 bomb */
  172.     while (scrollBounds.size.width > 4096.0) {
  173.         // Simulate a zoom out
  174.         scrollBounds.size.width /= zoomfactor;
  175.         --curzoom;
  176.         zoomfactor /= 1.5;
  177.         scrollBounds.size.width *= zoomfactor;
  178.         printf("too big -- new width = %f\n", scrollBounds.size.width);
  179.     }
  180.     [myView sizeTo:scrollBounds.size.width :scrollBounds.size.height];
  181.     [myView getBounds:&viewBounds];
  182.     [myView lockFocus];
  183.     PSsetgray(NX_WHITE);
  184.     NXRectFill(&viewBounds);
  185.     [myView unlockFocus];
  186.     winwidth = scrollBounds.size.width;
  187.     zoomsize = frames;
  188.     step = 1.0*zoomsize/winwidth;
  189.     half = 1.0*(visBounds.size.height)/2.0;
  190.     yscalea = 1.0*(half - 25.0)/(1.0*(amax - amin));
  191.     yscalep = 1.0*(half - 25.0)/(1.0*(ptchmax - ptchmin));
  192.  
  193.     if (!PSAdata) PSAdata = (float *)malloc(4*winwidth*sizeof(float));
  194.     if (!PSPdata) PSPdata = (float *)malloc(4*winwidth*sizeof(float));
  195.     if (!PSops) PSops = (char *)malloc(2*winwidth*sizeof(char));
  196.  
  197.     pitchT = PSPdata + ((4*winwidth) - 1);
  198.     ampT = PSAdata + ((4*winwidth) - 1);
  199.     
  200.     t = lpcData;
  201.     belowthresh = 0;
  202.     abovethresh = 0;
  203.     for (i = 0, a = PSAdata, ptch = PSPdata, o = PSops; 
  204.         i < winwidth; i++) {
  205.         if (t[THRESH] < threshold) {
  206.             *a++ = i;
  207.             *a++ = 20.0;
  208.             *a++ = 0.0;
  209.             *a++ = ((t[AMP] - amin)*yscalea);
  210.  
  211.             *ptch++ = i;    
  212.             *ptch++ = half+20.0;
  213.             *ptch++ = 0.0;
  214.             *ptch++ = ((t[PITCH] - ptchmin)*yscalep);
  215.             belowthresh++;
  216.         }
  217.         else {
  218.             *ampT-- = ((t[AMP] - amin)*yscalea);
  219.             *ampT-- = 20.0;
  220.             *ampT-- = 0.0;
  221.             *ampT-- = i;
  222.             
  223.             *pitchT-- = ((t[PITCH] - ptchmin)*yscalep);
  224.             *pitchT-- = 0.0;
  225.             *pitchT-- = half+20.0;
  226.             *pitchT-- = i;
  227.             abovethresh++;
  228.         }
  229.         *o++ = dps_moveto;
  230.         *o++ = dps_rlineto;
  231.  
  232.         t = (lpcData) + (framesize * (int)(i * step));
  233.     }
  234.     ampT++;
  235.     pitchT++;
  236.     bbox[0] = 0.0;
  237.     bbox[1] = 0.0;
  238.     bbox[2] = winwidth;
  239.     bbox[3] = ((amax - amin)*yscalea) + half;
  240.     [myView drawPlot:PSAdata:PSops:bbox:belowthresh:NX_BLACK];
  241.     [myView drawPlot:ampT:PSops:bbox:abovethresh:NX_DKGRAY];
  242.     bbox[1] = half;
  243.     bbox[3] = visBounds.size.height;
  244.     [myView drawPlot:PSPdata:PSops:bbox:belowthresh:NX_BLACK];
  245.     [myView drawPlot:pitchT:PSops:bbox:abovethresh:NX_DKGRAY];
  246.     [myView lockFocus];
  247.     PWdrawruler(0, frames,(20*frames/winwidth), (20*frames/winwidth)/step);
  248.     [myView unlockFocus];
  249.     if (PSAdata) free(PSAdata);
  250.     if (PSPdata) free(PSPdata);
  251.     if (PSops) free(PSops);
  252.     PSAdata = NULL;
  253.     PSPdata = NULL;
  254.     PSops = NULL;
  255.     return self;
  256. }
  257.  
  258. - show:sender
  259. {
  260.     [myPlot makeKeyAndOrderFront:self];
  261.     [myView display];
  262.     return self;
  263. }
  264.  
  265. - setPoles:(int)pole
  266. {
  267.     poles = pole;
  268.     return self;
  269. }
  270.  
  271. - (int)getPoles
  272. {
  273.     return poles;
  274. }
  275.  
  276.  
  277. - updateCursor:sender
  278. {
  279.     float    amp, pitch, *t;
  280.     int    cursor, width, frame1, frame2, temp;
  281.     
  282.     if (!hasData) 
  283.         return self;
  284.     cursor = [myView getcurPos];
  285.     width = [myView getWidth];
  286.     framesize = [self getPoles] + 4;
  287.  
  288.     frame1 = (int)(cursor * step);
  289.     frame2 = (int)((cursor + width) * step);
  290.     if (frame1 > frame2) {
  291.         temp = frame1;
  292.         frame1 = frame2;
  293.         frame2 = temp;
  294.     }
  295.     [startFrame setIntValue:frame1];
  296.     [endFrame setIntValue:frame2];
  297.     t = lpcData + (framesize * (int)((cursor + width) * step));
  298.     amp = t[AMP];
  299.     pitch = t[PITCH];
  300.     [ampFrame setFloatValue:amp];
  301.     [pitchFrame setFloatValue:pitch];
  302.     return self;
  303. }
  304.  
  305. - changeCursor:sender
  306. {
  307.     int    frame1, frame2, temp;
  308.     float    loc, loc2, width;
  309.     
  310.     frame1 = [startFrame intValue];
  311.     frame2 = [endFrame intValue];
  312.  
  313.     frame1 = (frame1 < 0) ? 0 : frame1;
  314.     frame1 = (frame1 > frames) ? frames : frame1;
  315.     frame2 = (frame2 < 0) ? 0 : frame2;
  316.     frame2 = (frame2 > frames) ? frames : frame2;
  317.  
  318.     if (frame1 > frame2) {
  319.         temp = frame1;
  320.         frame1 = frame2;
  321.         frame2 = temp;
  322.     }
  323.     
  324.     loc = frame1 / step;
  325.     loc2 = frame2 / step;
  326.     width = loc2 - loc;
  327.     [myView changeCurs:loc:width];
  328.     return self;
  329. }
  330.  
  331. - selectAll:sender
  332. {
  333.     [myView changeCurs:0:(frames/step)];
  334.     return self;
  335. }
  336.  
  337.  
  338. - changeAmp:sender
  339. {
  340.     float    *t, val;
  341.     int    cursor, width, i, frame1, frame2, temp;
  342.     
  343.     cursor = [myView getcurPos];
  344.     width = [myView getWidth];
  345.     framesize = [self getPoles] + 4;
  346.     //t = lpcData + (framesize * (int)(cursor * step));
  347.     frame1 = (int)cursor * step;
  348.     frame2 = (int)(cursor + width) * step;
  349.     if (frame1 > frame2) {
  350.         temp = frame1;
  351.         frame1 = frame2;
  352.         frame2 = temp;
  353.     }
  354.     t = lpcData + (framesize * frame1);
  355.     val = [ampFrame floatValue];
  356.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  357.     for (i = frame1; i <= frame2; i++) {
  358.         t[AMP] = val;
  359.         t[RESIDAMP] = val;
  360.         t = (lpcData) + (framesize * (i + 1));
  361.     }
  362.     [myView display];
  363.     [self setDirty:YES];
  364.     return self;        
  365. }
  366.  
  367. - changePitch:sender
  368. {
  369.     float    *t, val;
  370.     int    cursor, width, i, frame1, frame2, temp;
  371.     
  372.     cursor = [myView getcurPos];
  373.     width = [myView getWidth];
  374.     framesize = [self getPoles] + 4;
  375.     //t = lpcData + (framesize * (int)(cursor * step));
  376.     frame1 = (int)cursor * step;
  377.     frame2 = (int)(cursor + width) * step;
  378.     if (frame1 > frame2) {
  379.         temp = frame1;
  380.         frame1 = frame2;
  381.         frame2 = temp;
  382.     }
  383.     t = lpcData + (framesize * frame1);
  384.     val = [pitchFrame floatValue];
  385.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  386.     for (i = frame1; i <= frame2; i++) {
  387.         t[PITCH] = val;
  388.         t = (lpcData) + (framesize * (i + 1));
  389.     }
  390.     [myView display];
  391.     [self setDirty:YES];
  392.     return self;
  393. }
  394.  
  395. - multiplyAmp:sender
  396. {
  397.     float    *t, val;
  398.     int    cursor, width, i, frame1, frame2, temp;
  399.     
  400.     cursor = [myView getcurPos];
  401.     width = [myView getWidth];
  402.     framesize = [self getPoles] + 4;
  403.     //t = lpcData + (framesize * (int)(cursor * step));
  404.     frame1 = (int)cursor * step;
  405.     frame2 = (int)(cursor + width) * step;
  406.     if (frame1 > frame2) {
  407.         temp = frame1;
  408.         frame1 = frame2;
  409.         frame2 = temp;
  410.     }
  411.     val = [mulAmpFrame floatValue];
  412.     t = lpcData + (framesize * frame1);
  413.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  414.     for (i = frame1; i <= frame2; i++) {
  415.         t[AMP] *= val;
  416.         t[RESIDAMP] *= val;
  417.         t = (lpcData) + (framesize * (i + 1));
  418.     }
  419.     [myView display];
  420.     return self;
  421. }
  422.  
  423. - multiplyPitch:sender
  424. {
  425.     float    *t, val, top, bottom;
  426.     int    cursor, width, i, frame1, frame2, temp;
  427.     
  428.     cursor = [myView getcurPos];
  429.     width = [myView getWidth];
  430.     framesize = [self getPoles] + 4;
  431.     //t = lpcData + (framesize * (int)(cursor * step));
  432.     frame1 = (int)cursor * step;
  433.     frame2 = (int)(cursor + width) * step;
  434.     if (frame1 > frame2) {
  435.         temp = frame1;
  436.         frame1 = frame2;
  437.         frame2 = temp;
  438.     }
  439.     t = lpcData + (framesize * frame1);
  440.     val = [mulPitchFrame floatValue];
  441.     top = [topPitchFrame floatValue];
  442.     bottom = [botPitchFrame floatValue];
  443.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  444.     for (i = frame1; i <= frame2; i++) {
  445.         if (t[PITCH] <= top && t[PITCH] >= bottom)
  446.             t[PITCH] *= val;
  447.         t = (lpcData) + (framesize * (i + 1));
  448.     }
  449.     [myView display];
  450.     [self setDirty:YES];
  451.     return self;
  452. }
  453.  
  454. - interpolate:sender
  455. {
  456.     float    *t, *v, first, last, scale;
  457.     int    cursor, width, i, frame1, frame2, temp, j;
  458.     
  459.     cursor = [myView getcurPos];
  460.     width = [myView getWidth];
  461.     framesize = [self getPoles] + 4;
  462.     frame1 = ((int)(cursor * step)) - 1;
  463.     frame2 = ((int)((cursor + width) * step)) + 1;
  464.     if (frame1 > frame2) {
  465.         temp = frame1;
  466.         frame1 = frame2;
  467.         frame2 = temp;
  468.     }
  469.     t = lpcData + (framesize * frame1);
  470.     v = lpcData + (framesize * frame2);
  471.     first = t[PITCH];
  472.     last = v[PITCH]; 
  473.     //t = lpcData + (framesize * (int)(cursor * step));
  474.     t = lpcData + (framesize * frame1);
  475.     scale = (last - first) / (frame2 - frame1);
  476.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  477.     for (i = frame1, j = 0; i <= frame2; i++) {
  478.         t[PITCH] = first + (j * scale);
  479.         t = (lpcData) + (framesize * (i + 1));
  480.         ++j;
  481.     }
  482.     [myView display];
  483.     [self setDirty:YES];
  484.     return self;
  485. }
  486.  
  487. - addError:sender
  488. {
  489.     float    *t, val;
  490.     int    cursor, width, i, frame1, frame2, temp;
  491.     
  492.     cursor = [myView getcurPos];
  493.     width = [myView getWidth];
  494.     framesize = [self getPoles] + 4;
  495.     //t = lpcData + (framesize * (int)(cursor * step));
  496.     frame1 = (int)cursor * step;
  497.     frame2 = (int)(cursor + width) * step;
  498.     if (frame1 > frame2) {
  499.         temp = frame1;
  500.         frame1 = frame2;
  501.         frame2 = temp;
  502.     }
  503.     t = lpcData + (framesize * frame1);
  504.     val = [addErrFrame floatValue];
  505.     [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t];
  506.     for (i = frame1; i <= frame2; i++) {
  507.         t[THRESH] += val;
  508.         t = (lpcData) + (framesize * (i + 1));
  509.     }
  510.     [myView display];
  511.     [self setDirty:YES];
  512.     return self;    
  513. }
  514.  
  515. - save:sender
  516. {
  517.     id    sPanel;
  518.     
  519.     sPanel = [SavePanel new];
  520.     if (!strcmp("Untitled", filename)) {
  521.         if ([sPanel runModal]) {
  522.             strcpy(filename, [sPanel filename]);
  523.             [myPlot setTitleAsFilename:filename];
  524.             openfd = open(filename, O_RDWR|O_CREAT, 0644);
  525.             if (openfd < 0) {
  526.                 [self error:"Error opening input file : ":errno];
  527.                 return self;
  528.             }
  529.             if (write(openfd, (char *)lpcData, numBytes) < 0) {
  530.                 [self error:"Error writing file : ":errno];
  531.                 return self;
  532.             };
  533.             [self setDirty:NO];
  534.             return self;
  535.         }
  536.     } 
  537.     else {
  538.         lseek(openfd, 0, 0);  // start of file
  539.         if (write(openfd,(char *)lpcData,numBytes) < 0) {
  540.             [self error:"Error writing file : ":errno];
  541.             return self;
  542.         }
  543.         [self setDirty:NO];
  544.         return self;
  545.     }
  546.     return self;
  547. }
  548.  
  549. - saveAs:sender
  550. {
  551.     id    sPanel;
  552.     char    dir[1024],  *file;
  553.     
  554.     sPanel = [SavePanel new];
  555.     file = rindex(filename, '/') + 1;
  556.     strncpy(dir, filename, (int)(file - filename));
  557.     if ([sPanel runModalForDirectory:dir file:file]) {
  558.         if (strcmp(filename, [sPanel filename])) {
  559.             strcpy(filename, [sPanel filename]);
  560.             close(openfd);
  561.             openfd = open(filename, O_RDWR|O_CREAT, 0644);
  562.             if (openfd < 0) {
  563.                 [self error:"Error saving file : ":errno];
  564.                 return self;
  565.             }
  566.             if (write(openfd, (char *)lpcData, numBytes) < 0) {
  567.                 [self error:"Error saving file : ":errno];
  568.                 return self;
  569.             }
  570.             [myPlot setTitleAsFilename:filename];
  571.             [self setDirty:NO];
  572.             return self;
  573.         }
  574.         else {
  575.             lseek(openfd, 0, 0);
  576.             if (write(openfd, (char *)lpcData, numBytes) < 0) {
  577.                 [self error:"Error saving file : ":errno];
  578.                 return self;
  579.             }
  580.             [self setDirty:NO];
  581.             return self;
  582.         }
  583.     }
  584.     return self;
  585. }
  586.  
  587. - print:sender
  588. {
  589.     [myView printPSCode:self];
  590.     return self;
  591. }
  592.  
  593. - plot
  594. {
  595.     return myPlot;
  596. }
  597.  
  598. - zoomIn:sender
  599. {
  600.     NXRect foo;
  601.     
  602.     if (curzoom >= MAXZOOM) 
  603.         return self;
  604.     [myView getBounds:&foo];
  605.     if ((foo.size.width * 1.5) > 4096.0)
  606.         return self;
  607.     ++curzoom;
  608.     zoomfactor *= 1.5;
  609.     [myView display];    
  610.     return self;
  611. }
  612.  
  613. - zoomOut:sender
  614. {
  615.     if (curzoom <= MINZOOM)
  616.         return self;
  617.     --curzoom;
  618.     zoomfactor /= 1.5;
  619.     [myView display];
  620.     return self;
  621. }
  622.  
  623. - setThreshold:sender
  624. {
  625.     threshold = [threshFrame floatValue];
  626.     [myView display];
  627.     return self;
  628. }
  629.  
  630. - doCopy:(NXStream *)selection
  631. {
  632.     float    *t;
  633.     int    cursor, width, frame1, frame2, temp, bytes;
  634.     
  635.     if (!hasData) {
  636.         return self;
  637.     }
  638.     cursor = [myView getcurPos];
  639.     width = [myView getWidth];
  640.     framesize = [self getPoles] + 4;
  641.     //t = lpcData + (framesize * (int)(cursor * step));
  642.     frame1 = (int)cursor * step;
  643.     frame2 = (int)(cursor + width) * step;
  644.     if (frame1 > frame2) {
  645.         temp = frame1;
  646.         frame1 = frame2;
  647.         frame2 = temp;
  648.     }
  649.     t = lpcData + (framesize * frame1);
  650.     bytes =  (frame2 - frame1)*framesize*sizeof(float);
  651.     NXWrite(selection, t, bytes);
  652.     return self;
  653.     
  654. }
  655.  
  656. - doCut:(NXStream *)selection
  657. {
  658.     float    *t, *v;
  659.     int    cursor, width, i, frame1, frame2, temp, bytes;
  660.  
  661.     if (!hasData) {
  662.         return self;
  663.     }
  664.     cursor = [myView getcurPos];
  665.     width = [myView getWidth];
  666.     framesize = [self getPoles] + 4;
  667.     //t = lpcData + (framesize * (int)(cursor * step));
  668.     frame1 = (int)cursor * step;
  669.     frame2 = (int)(cursor + width) * step;
  670.     if (frame1 > frame2) {
  671.         temp = frame1;
  672.         frame1 = frame2;
  673.         frame2 = temp;
  674.     }
  675.     t = lpcData + (framesize * frame1);
  676.     bytes =  (frame2 - frame1)*framesize*sizeof(float);
  677.     NXWrite(selection, t, bytes);
  678.     numBytes -= bytes;
  679.     frames = (numBytes/(([self getPoles] + 4)*4))-1;
  680.     [numFrames setIntValue:frames];
  681.     v = t + (bytes / sizeof(float));
  682.     for (i = 0; i < (bytes / sizeof(float)); i++) {
  683.         *t++ = *v++;
  684.     }
  685.     realloc(lpcData, numBytes);
  686.     [myView display];
  687.     [self setDirty:YES];
  688.     return self;
  689.     
  690. }
  691.  
  692. - doInsert:(float *)data :(int) bytes
  693. {
  694.     int    cursor, frame1, size, i;
  695.     float    *t, *v;
  696.     
  697.     if (!hasData) {
  698.         hasData = 1;
  699.         lpcData = (float *)malloc(bytes);
  700.         numBytes = bytes;
  701.         frames = (numBytes/(([self getPoles] + 4)*4)) - 1;
  702.         [numFrames setIntValue:frames];
  703.         t = lpcData;
  704.         for (i = 0; i < (bytes / sizeof(float)); i++) {
  705.             *t++ = *data++;
  706.         }
  707.         [myView display];
  708.         return self;
  709.     }
  710.     numBytes += bytes;
  711.     frames = (numBytes/(([self getPoles] + 4)*4))-1;
  712.     [numFrames setIntValue:frames];
  713.     realloc(lpcData, numBytes);
  714.     cursor = [myView getcurPos];
  715.     frame1 = (int)cursor * step;
  716.     framesize = [self getPoles] + 4;
  717.     size = (numBytes - bytes) - (frame1 * framesize * sizeof(float));
  718.  
  719.     v = lpcData + (numBytes / sizeof(float)) - 1;
  720.     t = lpcData + ((numBytes - bytes) / sizeof(float)) - 1;
  721.     for (i = 0; i < (size / sizeof(float)); i++) {
  722.         *v-- = *t--;
  723.     }
  724.     t = lpcData + (framesize * frame1);
  725.     for (i = 0; i < (bytes / sizeof(float)); i++) {
  726.         *t++ = *data++;
  727.     }
  728.     [myView display];
  729.     [self setDirty:YES];
  730.     return self;
  731. }
  732.  
  733. - saveundo:(int)size: (float *)data
  734. {
  735.     int    i;
  736.     float    *t, *s;
  737.     
  738.     if (undoData) 
  739.         free(undoData);
  740.     undoData = (float *)malloc(size);
  741.     undoLoc = data;
  742.     undoSize = size;
  743.     t = undoData;
  744.     s = data;
  745.     for (i = 0; i < (undoSize / 4); i++) {
  746.         *t++ = *s++;
  747.     }
  748.     return self;
  749. }
  750.  
  751. - undo:sender
  752. {
  753.     float    *t, *s;
  754.     int    i;
  755.     
  756.     t = undoLoc;
  757.     s = undoData;
  758.     for (i = 0; i < (undoSize / 4); i++) {
  759.         *t++ = *s++;
  760.     }
  761.     [myView display];
  762.     return self;
  763. }
  764.  
  765. - error:(char *)msg:(int)num
  766. {
  767.     if (num)
  768.         NXRunAlertPanel("Alert", "%s : %s", "OK", NULL, NULL, msg, strerror(num));
  769.     else
  770.         NXRunAlertPanel("Alert", "%s", "OK", NULL, NULL, msg);
  771.     return self;
  772. }
  773.  
  774. - windowWillClose:sender
  775. {
  776.     if ([myPlot isDocEdited]) {
  777.         switch (NXRunAlertPanel("Alert", "Plot has been edited.  Do you want to save?", "Yes", "No", "Cancel")) {
  778.             case NX_ALERTDEFAULT :
  779.                 [self saveAs:self];
  780.                 break;
  781.             case NX_ALERTOTHER :
  782.                 return nil;
  783.                 break;
  784.             default :
  785.                 break;
  786.         }
  787.     }
  788.     return self;
  789. }
  790.  
  791. - setDirty:(BOOL)val
  792. {
  793.     [myPlot setDocEdited:val];
  794.     dirty = val;
  795.     return self;
  796. }
  797.  
  798. - (BOOL)isDirty
  799. {
  800.     return dirty;
  801. }
  802.  
  803. - cursorSel:sender
  804. {
  805.     [myView setCursorType:SELECTION];
  806.     return self;
  807. }
  808.  
  809. - cursorHair:sender
  810. {
  811.     [myView setCursorType:HAIRLINE];
  812.     return self;
  813. }
  814.  
  815. @end
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.